// Copyright ©2018 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build ignore

package main

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/parser"
	"go/printer"
	"go/token"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

const (
	srcModule = "gonum.org/v1/gonum"
	errorFile = "lapack/gonum/errors.go"
)

func main() {
	path, err := pathTo(srcModule, errorFile)
	if err != nil {
		log.Fatalf("no source for %q: %v", errorFile, err)
	}

	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
	if err != nil {
		log.Fatalf("failed to parse %q: %v", path, err)
	}

	dst := filepath.Base(errorFile)
	o, err := os.Create(dst)
	if err != nil {
		log.Fatalf("failed to create %q: %v", dst, err)
	}
	defer o.Close()

	fmt.Fprintln(o, header)
	for _, cg := range f.Comments {
		for _, c := range cg.List {
			fmt.Fprintln(o, c.Text)
		}
		break
	}
	fmt.Fprintln(o, pkg)
	p := printer.Config{
		Mode:     printer.UseSpaces | printer.TabIndent,
		Tabwidth: 8,
	}
	// Remove comment associated with the const block.
	for _, d := range f.Decls {
		if d, ok := d.(*ast.GenDecl); ok {
			d.Doc = nil
		}
	}
	p.Fprint(o, fset, f.Decls)
	fmt.Fprintln(o)
}

// pathTo returns the path to file within the given module. If running
// in module mode, this will look within the module in $GOPATH/pkg/mod
// at the correct version, otherwise it will find the version installed
// at $GOPATH/src/module/file.
func pathTo(module, file string) (string, error) {
	gopath, ok := os.LookupEnv("GOPATH")
	if !ok {
		var err error
		gopath, err = os.UserHomeDir()
		if err != nil {
			return "", err
		}
		gopath = filepath.Join(gopath, "go")
	}

	cmd := exec.Command("go", "list", "-m", module)
	var buf, stderr bytes.Buffer
	cmd.Stdout = &buf
	cmd.Stderr = &stderr
	err := cmd.Run()
	if err != nil {
		return "", fmt.Errorf("module aware go list failed with stderr output %q: %w", stderr.String(), err)
	}
	version := strings.TrimSpace(strings.Join(strings.Split(buf.String(), " "), "@"))
	return filepath.Join(gopath, "pkg", "mod", version, file), nil
}

const (
	header = `// Code generated by "go generate gonum.org/v1/netlib/lapack/netlib”; DO NOT EDIT.
`
	pkg = `
package netlib

// Copied from gonum/lapack/gonum. Keep in sync.`
)
